﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Kimd.Common
{
    public class ModelHelper<T> where T : class
    {
        public Dictionary<string, Type> ModelTypes = new Dictionary<string, Type>();
        public Dictionary<string, T> ModelInstances = new Dictionary<string, T>();
        public Dictionary<string, string> AssemblyVersion = new Dictionary<string, string>();

        public void LoadTypes(string dir, string dllName = "")
        {
            ModelTypes.Clear();
            string addInDir = AppDomain.CurrentDomain.BaseDirectory;
            var UserAssembliesFiles = string.IsNullOrEmpty(dllName) ? Directory.EnumerateFiles(addInDir + $"{dir}", "*.dll") : Directory.EnumerateFiles(addInDir + $"{dir}", $"{dllName}.dll");
            var assemblies = UserAssembliesFiles.Select(file => Assembly.LoadFile(file));
            foreach (Assembly asb in assemblies)
            {
                AssemblyVersion.Add(asb.GetName().Name, asb.GetName().Version.ToString());
            }
            var stepTypes = from assembly in assemblies
                            from t in assembly.ExportedTypes
                            where t.IsClass && !t.IsAbstract && typeof(T).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())
                            select t;
            foreach (Type item in stepTypes)
            {
                ModelTypes.Add(item.Name, item);
            }
        }
        public void LoadTypes2(string dir, string dllName = "")
        {
            ModelTypes.Clear();
            var UserAssembliesFiles = string.IsNullOrEmpty(dllName) ? Directory.EnumerateFiles(dir, "*.dll") : Directory.EnumerateFiles(dir, $"{dllName}.dll");
            var assemblies = UserAssembliesFiles.Select(file => Assembly.LoadFile(file));
            foreach (Assembly asb in assemblies)
            {
                AssemblyVersion.Add(asb.GetName().Name, asb.GetName().Version.ToString());
            }
            var stepTypes = from assembly in assemblies
                            from t in assembly.ExportedTypes
                            where t.IsClass && !t.IsAbstract && typeof(T).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())
                            select t;
            foreach (Type item in stepTypes)
            {
                ModelTypes.Add(item.Name, item);
            }
        }

        public void LoadInstances()
        {
            ModelInstances.Clear(); 
            T model = null;
            foreach (Type type in ModelTypes.Values)
            {
                model = Activator.CreateInstance(type) as T;
                string temp = model.ToString();
                string name = temp.Split('.').Last();
                if (!ModelInstances.ContainsKey(name))
                    ModelInstances.Add(name, model);
            }
        }
    }
}
